#include <adcMeasurementTask.h>

#define ADC_SAMPLING_NUM   8

typedef struct{
  uint16_t vbatAdcCount;
  uint16_t vTempAdcCount;
  uint16_t vLedAdcCount[3];
  uint16_t samplingCount;
  
  uint16_t vbatVolt;
  uint16_t vTempVolt;
  uint16_t vLedVolt[3];
}AdcResult_t;

AdcResult_t adcResult;

TaskState_t adcTaskState = TASK_STATE_INIT;
AdcMeasureItem_t adcItem = ADC_MEASURE_ITEM_NONE;

void ADCMeasureTimerExpired(SoftTimer_t *timer);

SoftTimer_t adcMeasureTimerTimer = {
    .mode     = SYS_TIMER_PERIODIC_MODE,
    .interval = 200,
    .handler  = ADCMeasureTimerExpired
};

void ADCMeasureTimerExpired(SoftTimer_t *timer)
{
    TM_PostTask(TASK_ID_ADC);
}


void ADCMeasureResult_ISR(AdcMeasureItem_t item, uint16_t value)
{
    switch(adcItem){
    case ADC_MEASURE_ITEM_VBAT:
      adcResult.vbatAdcCount +=value;
      break;
    case ADC_MEASURE_ITEM_VTEMP:
      adcResult.vTempAdcCount +=value;
      break;
    case ADC_MEASURE_ITEM_VLED0:
      adcResult.vLedAdcCount[0] +=value;
      break;
    case ADC_MEASURE_ITEM_VLED1:
      adcResult.vLedAdcCount[1] +=value;
      break;
    case ADC_MEASURE_ITEM_VLED2:
      adcResult.vLedAdcCount[2] +=value;
      break;
    }
    adcResult.samplingCount ++;
    TM_PostTask(TASK_ID_ADC);
}


void adcMeasureQueue(void)
{
    switch(adcItem){
    case ADC_MEASURE_ITEM_NONE:
      adcResult.vbatAdcCount = 0;
      adcResult.samplingCount = 0;
      adcItem = ADC_MEASURE_ITEM_VBAT;
      break;
    case ADC_MEASURE_ITEM_VBAT:
      if (adcResult.samplingCount >= ADC_SAMPLING_NUM){
          adcResult.vTempAdcCount = 0;
          adcResult.samplingCount = 0;
          adcItem = ADC_MEASURE_ITEM_VTEMP;
      }
      break;
    case ADC_MEASURE_ITEM_VTEMP:
      if (adcResult.samplingCount >= ADC_SAMPLING_NUM){
          adcResult.vLedAdcCount[0] = 0;
          adcResult.samplingCount = 0;
          adcItem = ADC_MEASURE_ITEM_VLED0;
      }
      break;
    case ADC_MEASURE_ITEM_VLED0:
      if (adcResult.samplingCount >= ADC_SAMPLING_NUM){
          adcResult.vLedAdcCount[1] = 0;
          adcResult.samplingCount = 0;
          adcItem = ADC_MEASURE_ITEM_VLED1;
      }
      break;
    case ADC_MEASURE_ITEM_VLED1:
      if (adcResult.samplingCount >= ADC_SAMPLING_NUM){
          adcResult.vLedAdcCount[2] = 0;
          adcResult.samplingCount = 0;
          adcItem = ADC_MEASURE_ITEM_VLED2;
      }
      break;
    case ADC_MEASURE_ITEM_VLED2:
      if (adcResult.samplingCount >= ADC_SAMPLING_NUM){
          adcResult.samplingCount = 0;
          adcItem = ADC_MEASURE_ITEM_NONE;
      }
      break;
    default:
      adcItem = ADC_MEASURE_ITEM_NONE;
      break;
    }
    if (adcItem != ADC_MEASURE_ITEM_NONE){
        ADC_Init(adcItem);
        ADC_RegisterIRQ(ADCMeasureResult_ISR);
        ADC_Start();
    }
}


int16_t ADCM_GetVBatVolt(void)
{
    return adcResult.vbatVolt;
}

int16_t ADCM_GetVTempVolt(void)
{
    return adcResult.vTempVolt;
}

int16_t ADCM_GetVLedVolt(uint8_t index)
{
    if (index >= 3){
      return -1;
    }
    return adcResult.vLedVolt[index];
}

void ADC_TaskHandler(void)
{
    switch(adcTaskState){
    case TASK_STATE_INIT:
      SoftTimer_Start(&adcMeasureTimerTimer);
      adcTaskState = TASK_STATE_ACTIVE;
      adcItem = ADC_MEASURE_ITEM_NONE;
      break;
    case TASK_STATE_ACTIVE:
      adcMeasureQueue();
      break;
    }
}


